package com.yjymm.edu.service.impl;

import com.alipay.api.domain.Money;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yjymm.edu.common.DateTimeUtils;
import com.yjymm.edu.common.MyBeanUtils;
import com.yjymm.edu.common.StringUtils;
import com.yjymm.edu.common.constant.UserLogConstant;
import com.yjymm.edu.exception.MyException;
import com.yjymm.edu.mapper.MoneyLogMapper;
import com.yjymm.edu.mapper.UserLogMapper;
import com.yjymm.edu.mapper.UserMapper;
import com.yjymm.edu.model.dto.RechargeDTO;
import com.yjymm.edu.model.entity.*;
import com.yjymm.edu.mapper.RechargeMapper;
import com.yjymm.edu.service.RechargeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.List;

/**
 * @author yjymm
 * @since 2020-12-25
 */
@Service
public class RechargeServiceImpl extends ServiceImpl<RechargeMapper, Recharge> implements RechargeService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserLogMapper userLogMapper;

    @Resource
    private MoneyLogMapper moneyLogMapper;

    /**
     * 当单超时时间 30分钟
     */
    public static final Integer RECHARGE_OVERTIME_MINUTE = 30;

    @Override
    @Transactional
    public Recharge insert(RechargeDTO rechargeDTO) throws Exception {
        Recharge recharge = MyBeanUtils.copyProperties2Object(rechargeDTO, Recharge.class);
        recharge.setRechargeNum(StringUtils.getRandomString("recharge"));
        int insert = baseMapper.insert(recharge);
        if (insert <= 0) {
            throw new SQLException("创建充值订单失败");
        }
        return recharge;
    }

    /**
     * @param rid
     * @param uid
     * @param rechargeCode 0:取消充值，1：确定充值
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @Deprecated
    public void doRecharge(Integer rid, Integer uid, Integer rechargeCode) throws Exception {
        QueryWrapper<Recharge> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("id", rid).eq("uid", uid);
        Recharge recharge = baseMapper.selectOne(objectQueryWrapper);

        if (recharge.getFinished() >= 4 || recharge.getFinished() < 0) {
            // TODO: 2021/3/26 通知管理员用户充值订单异常
            throw new MyException("订单异常，已通知管理员");
        }

        if (recharge.getFinished() == 2) {
            throw new MyException("此订单已被取消，充值失败");
        }
        if (recharge.getFinished() == 1) {
            throw new MyException("此订单已完成，无法继续操作");
        }
        // 判断订单是否超时
        if (checkIsOverTime(recharge)) {
            throw new MyException("您的此订单已超时，请重新充值");
        }

        if (rechargeCode == 0) {
            // 确认取消
            recharge.setFinished(2);
        } else if (rechargeCode == 1) {
            // 确认充值
            recharge.setFinished(1);
            recharge.setRechargeTime(LocalDateTime.now());
        }
        recharge.setFinishTime(LocalDateTime.now());
        baseMapper.updateById(recharge);
        //更新用户余额
        User user = userMapper.selectById(uid);
//        user.setBalance(user.getBalance() + recharge.getMoney());
        user.setBalance(user.getBalance().add(recharge.getMoney()));
        userMapper.updateById(user);

    }

    @Override
    public List<Recharge> getListByUid(Integer uid) {
        QueryWrapper<Recharge> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("uid", uid);
        List<Recharge> recharges = baseMapper.selectList(objectQueryWrapper);

        sortedByCreateTime(recharges);
        return recharges;
    }

    /**
     * 充值订单创建时间降序排序
     *
     * @param list
     */
    @Override
    public void sortedByCreateTime(List<Recharge> list) {
        list.sort((a, b) -> {
            long aa = a.getCreateTime().toEpochSecond(ZoneOffset.of("+8"));
            long bb = b.getCreateTime().toEpochSecond(ZoneOffset.of("+8"));
            return bb > aa ? 1 : -1;
        });
    }

    /**
     * 判断订单是否超时
     *
     * @param recharge
     */
    @Override
    public Boolean checkIsOverTime(Recharge recharge) {
        if (recharge.getFinished() == 3) {
            return true;
        }
        LocalTime now = LocalTime.now();
        LocalTime localTime = recharge.getCreateTime().toLocalTime().plusMinutes(30);
        if (now.compareTo(localTime) >= 0) {
            // 更新订单状态
            Recharge recharge1 = new Recharge();
            recharge1.setId(recharge.getId());
            recharge1.setFinished(3);
            baseMapper.updateById(recharge1);
            return true;
        }
        return false;
    }

    /**
     * 充值成功，修改用户账户余额
     *
     * @param rechargeNum
     * @return
     */
    @Override
    @Transactional
    public Boolean pay(String rechargeNum) {
        Recharge recharge = baseMapper.selectByRechargeNum(rechargeNum);
        User user = userMapper.selectById(recharge.getUid());
        // 确认充值
        recharge.setFinished(1);
        recharge.setRechargeTime(LocalDateTime.now());
        recharge.setFinishTime(LocalDateTime.now());
        baseMapper.updateById(recharge);

        // 用户金额变动记录
        MoneyLog moneyLog = MoneyLog.builder()
                .createTime(LocalDateTime.now())
                .balance(user.getBalance())
                .freezeBalance(user.getFreezeBalance())
                .money(recharge.getMoney())
                .description(UserLogConstant.DO_RECHARGE)
                .state(0)
                .uid(user.getId())
                .build();
        moneyLogMapper.insert(moneyLog);

        String s = String.format(UserLogConstant.USER_ALIPAY, DateTimeUtils.formatStr(LocalDateTime.now()),
                recharge.getMoney().doubleValue(), recharge.getRechargeNum());
        UserLog userLog = UserLog.builder()
                .state(0)
                .uid(user.getId())
                .createTime(LocalDateTime.now())
                .description(s)
                .build();
        userLogMapper.insert(userLog);

        //更新用户余额
//        user.setBalance(user.getBalance() + recharge.getMoney());
        user.setBalance(user.getBalance().add(recharge.getMoney()));
        userMapper.updateById(user);

        return Boolean.TRUE;
    }

    /**
     * 获取用户充值订单数
     * @param id
     * @return
     */
    @Override
    public Integer getUserRechargeCount(Integer uid) {
        return baseMapper.getUserRechargeCount(uid);
    }

    /**
     * 获取用户充值成功次数
     * @param id
     * @return
     */
    @Override
    public Integer getUserSuccessRechargeCount(Integer uid) {
        return baseMapper.getUserSuccessRechargeCount(uid);
    }

    @Override
    public Integer getCount() {
        QueryWrapper<Recharge> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted",0);
        Integer integer = baseMapper.selectCount(queryWrapper);
        return integer;
    }
}
